package ru.compscicenter.uno.util;

import com.mortennobel.imagescaling.ResampleOp;
import ru.compscicenter.uno.log.Logger;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * Created by IntelliJ IDEA.
 * User: Павел
 * Date: 29.04.12
 * Time: 11:42
 * <p/>
 * Класс служит хранилищем всех использованных картинок, предоставляет услуги по их загрузке и ресайзу.
 * Этот класс предоставляет унифицированный доступ к любым ихображениям, хранящимся в ресурсах.
 */
public class ImagePool {
    private static final Map<ImageDescriptor, BufferedImage> resizedImages = new HashMap<ImageDescriptor, BufferedImage>();
    private static final Map<ImageDescriptor, BufferedImage> originalImages = new HashMap<ImageDescriptor, BufferedImage>();

    private static class ImageDescriptor {
        private final String path;
        private final int width;
        private final int height;

        private ImageDescriptor(String path, int width, int height) {
            this.path = path;
            this.width = width;
            this.height = height;
        }

        //for original images
        private ImageDescriptor(String path) {
            this.path = path;
            width = 0;
            height = 0;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) return true;
            if (o == null || getClass() != o.getClass()) return false;

            ImageDescriptor that = (ImageDescriptor) o;

            if (height != that.height) return false;
            if (width != that.width) return false;
            if (path != null ? !path.equals(that.path) : that.path != null) return false;

            return true;
        }

        @Override
        public int hashCode() {
            int result = path != null ? path.hashCode() : 0;
            result = 31 * result + width;
            result = 31 * result + height;
            return result;
        }
    }

    public static BufferedImage getImage(String path, int width, int height) {
        //searching image via image descriptor
        ImageDescriptor imageDescriptor = new ImageDescriptor(path, width, height);
        if (resizedImages.containsKey(imageDescriptor)) {
            //image found in resized pool
            return resizedImages.get(imageDescriptor);
        } else {
            //image not found in in resized pool

            //searching original image
            ImageDescriptor originalImageDescriptor = new ImageDescriptor(path);
            if (originalImages.containsKey(originalImageDescriptor)) {
                //resizing
                BufferedImage resized = resizeImage(originalImages.get(originalImageDescriptor), width, height);
                if (resized != null) {
                    resizedImages.put(imageDescriptor, resized);
                    return resized;
                } else {
                    return null;
                }
            } else {
                //loading image
                BufferedImage original = loadImage(path);
                if (original == null) {
                    Logger.write("Cannot load image resource " + path + "(" + width + ", " + height + ") :", Logger.Mode.ERROR);
                    return null;
                }

                //adding original image to pool
                originalImages.put(new ImageDescriptor(path), original);

                //checking if resize required
                if (original.getWidth() == width && original.getHeight() == height) {
                    return original;
                }

                //resizing
                BufferedImage resized = resizeImage(original, width, height);
                if (resized != null) {
                    resizedImages.put(imageDescriptor, resized);
                    return resized;
                } else {
                    return null;
                }
            }
        }
    }

    private static BufferedImage loadImage(String path) {
        try {
            return ImageIO.read(new File(path));
        } catch (IOException e) {
            return null;
        }
    }

    private static BufferedImage resizeImage(BufferedImage src, int width, int height) {
        if (width > 0 && height > 0 && src != null) {
            ResampleOp resampleOp = new ResampleOp(width, height);
            return resampleOp.filter(src, null);
        } else {
            return null;
        }
    }
}
